# -*-coding:utf-8-*-

from bson.objectid import ObjectId
from daos.base_async import BaseDao, BaseRecord
from tornado.gen import coroutine, Return
from utils.misc import limit_update_scope

Products_Document_Structure = {
    '_id': 'PRODUCT_ID',
    'uid': 'USER_ID',
    'type': 'service|goods',  # 商品类型：服务或普通商品
    'name': 'filter #1',
    'desc': 'DESC',
    'desc_url': 'DESC_URL',  # 商品介绍页面
    'image_url': 'IMAGE_URL',  # 预览图片地址
    'notify_url': 'NOTIFY_URL',  # 在商品上发生的操作，如购买服务，下单，最后会将相关数据 POST 到该 URL
    'unit_price': 69.9,  # 商品当前单价
    'orig_unit_price': 79.9,  # 商品原始单价
    'tags': ['filter', 'wpm'],  # 商品标签，关键字
    'order': 'ORDER',  # 该字段用于支持在前端对列表进行排序
}


class Product(BaseRecord):
    def __getattr__(self, item):
        if 'unit_price' == item:
            return float(self._get_optional_field(item))
        else:
            return self._get_optional_field(item)


class ProductsDao(BaseDao):
    def __init__(self, db):
        super(ProductsDao, self).__init__(db, 'products')

    def _get_record_object(self, data):
        return Product(data)

    @coroutine
    def create_product(self, uid, data):
        required_fields = ['name', 'desc', 'desc_url', 'image_url', 'unit_price', 'orig_unit_price', 'type']
        optional_fields = ['notify_url', 'tags', 'order', 'specifics']
        data = self.extract_fields(data, required_fields=required_fields, optional_fields=optional_fields)
        if 'tags' in data and not isinstance(data['tags'], list):
            raise Exception('tags field must be list')
        data.update(uid=uid)
        result = yield self.insert_one(data)
        result = {'product_id': str(result.inserted_id)}
        raise Return(result)

    @coroutine
    def update_product(self, uid, pid, data):
        optional_fields = ['name', 'desc', 'desc_url', 'image_url', 'unit_price', 'orig_unit_price',
                           'notify_url', 'tags', 'order']
        data = self.extract_fields(data, optional_fields=optional_fields)
        if 'tags' in data and not isinstance(data['tags'], list):
            raise Exception('tags field must be list')
        filter_cond = {'uid': uid, '_id': ObjectId(pid)}
        update = {'$set': data}
        result = yield self.update_one(filter_cond, update)
        raise Return(1 == result.matched_count)

    @coroutine
    def get_product(self, uid, pid):
        filter_cond = {'uid': uid, '_id': ObjectId(pid)}
        result = yield self.find_one(filter_cond)
        result['product_id'] = str(result.pop('_id'))
        raise Return(result)

    @coroutine
    def delete_product(self, uid, pid):
        filter_cond = {'uid': uid, '_id': ObjectId(pid)}
        result = yield self.delete_one(filter_cond)
        raise Return(1 == result.deleted_count)

    @coroutine
    def update_product_specifics(self, uid, pid, data):
        filter_cond = {'uid': uid, '_id': ObjectId(pid)}
        update = limit_update_scope({'$set': data['specifics']})
        result = yield self.update_one(filter_cond, update)
        raise Return(1 == result.matched_count)

    @coroutine
    def get_product_specifics(self, uid, pid, field):
        filter_cond = {'uid': uid, '_id': ObjectId(pid)}
        result = yield self.get_sub_object_field(filter_cond, 'specifics', field)
        raise Return(result)
